package cn.com.scooper.config;

import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

/**
 * 配置单元，管理一个.properties文件
 * @author LuLihong
 *
 */
public class ConfigItem {
	private static final String B_TRUE = "true";
	private static final String B_FALSE = "false";

	private Properties properties = null;

	public ConfigItem(String fileName) {
		this(fileName, ConfigKit.DEFAULT_ENCODING);
	}

	public ConfigItem(String fileName, String encoding) {
		InputStream inputStream = null;
		try {
			inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName);
			if (inputStream == null) {
				throw new IllegalArgumentException("Properties file not found in classpath: " + fileName);
			}

			properties = new Properties();
			properties.load(new InputStreamReader(inputStream, encoding));
		} catch (IOException e) {
			throw new RuntimeException("Error loading properties file.", e);
		} finally {
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException e) {}
			}

		}
	}

	public ConfigItem(File file) {
		this(file, ConfigKit.DEFAULT_ENCODING);
	}

	public ConfigItem(File file, String encoding) {
		if (file == null) {
			throw new IllegalArgumentException("File can not be null.");
		}
		if (file.isFile() == false) {
			throw new IllegalArgumentException("File not found : " + file.getName());
		}

		InputStream inputStream = null;
		try {
			inputStream = new FileInputStream(file);
			properties = new Properties();
			properties.load(new InputStreamReader(inputStream, encoding));
		} catch (IOException e) {
			throw new RuntimeException("Error loading properties file.", e);
		} finally {
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException e) {
				}
			}
		}
	}

	public String get(String key) {
		return properties.getProperty(key);
	}

	public String get(String key, String defaultValue) {
		return properties.getProperty(key, defaultValue);
	}

	public Integer getInt(String key) {
		return getInt(key, null);
	}

	public Integer getInt(String key, Integer defaultValue) {
		String value = properties.getProperty(key);

		return (value == null) ? defaultValue : Integer.parseInt(value.trim());
	}

	public Long getLong(String key) {
		return getLong(key, null);
	}

	public Long getLong(String key, Long defaultValue) {
		String value = properties.getProperty(key);

		return (value == null) ? defaultValue : Long.parseLong(value.trim());
	}

	public Boolean getBoolean(String key) {
		return getBoolean(key, null);
	}

	public Boolean getBoolean(String key, Boolean defaultValue) {
		String value = properties.getProperty(key);
		if (value != null) {
			value = value.toLowerCase().trim();
			if (B_TRUE.equalsIgnoreCase(value)) {
				return true;
			} else if (B_FALSE.equalsIgnoreCase(value)) {
				return false;
			}

			throw new RuntimeException("The value can not parse to Boolean : " + value);
		}
		return defaultValue;
	}

	/**
	 * 在配置文件中查找配置项值，同时搜索该值中模式为{key}的部分，
	 * 将key提取出来，从配置文件中查询该key对应的值来替换{key}，支持多个{key}。
	 <br/>配置项如下：
	 <ul>
	 	<li>app.test.ip=192.168.103.172</li>
	 	<li>app.test.port=3306</li>
	 	<li>app.test.db=SSMS_DB</li>
	 	<li>app.test.url=jdbc:mysql://{app.test.ip}:{app.test.port}/{app.test.db}</li>
	 </ul>
	 获取的结果为：jdbc:mysql://192.168.103.172:3306/SSMS_DB
	 *
	 * @param configKey		配置项
	 * @return 替换后的配置项值
	 */
	public String getReplace(String configKey) {
		String configVal = get(configKey, "").trim();
		if (configVal == null || configVal.isEmpty()) {
			return "";
		}

		Set<String> replaceKeys = ConfigKit.parseReplaceKey(configVal);
		if (replaceKeys.size() == 0) {
			return configVal;
		}
		
		for (String replaceKey: replaceKeys) {
			String replaceValue = get(replaceKey, "").trim();
			replaceKey = "{" + replaceKey + "}";
			if (configVal.contains(replaceKey)) {
				configVal = configVal.replace(replaceKey, replaceValue);
			}
		}
		
		return configVal;
	}
	
	/**
	 * 根据前缀加载配置项
	 * @param prefix
	 * @return
	 */
	public Map<String, String> getByPrefix(String prefix) {
		Map<String, String> map = new HashMap<String, String>(5);
		
		if (prefix == null || prefix.isEmpty()) {
			return map;
		}
		
		for (String configKey: properties.stringPropertyNames()) {
			if (configKey.startsWith(prefix)) {
				String value = getReplace(configKey);
				map.put(configKey, value);
			}
		}
		
		return map;
	}

	public boolean containsKey(String key) {
		return properties.containsKey(key);
	}

	public Properties getProperties() {
		return properties;
	}
}
